package com.me.myFramework.myAop.aop300;

import com.me.myFramework.myAop.IBuy;
import com.me.myFramework.myAop.Xbox;
import com.me.myFramework.myAop.aop300.advice.method.AfterReturningAdvice;
import com.me.myFramework.myAop.aop300.advice.method.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * 自己实现 AOP-300：  <p></p>
 *
 * 把模板方法抽取到 advice接口，定义成方法执行前、正常返回、异常返回、环绕、执行后 5种增强（暂不支持多切面）
 *
 * @author ME
 * @date 2021/9/26
 */
public class MyAop300 {

    public static void main(String[] args) throws Throwable {
        ProxyFactory factory = new ProxyFactory(new Xbox());
        factory.addAdvisors(new DefaultPointcutAdvisor(new BeforeAdvice111()));
        factory.addAdvisors(new DefaultPointcutAdvisor(new AfterReturningAdvice222()));
        // TODO 因为代理只持有一个增强，所以不支持多切面

        IBuy proxy = (IBuy) factory.getProxy(Thread.currentThread().getContextClassLoader());

        System.out.println("\n----------------------- toString() ---------------------------------");
        System.out.println(proxy.toString());
        System.out.println();

        String result = proxy.buy("Jack");
    }

    /** 方法前的增强111 */
    static class BeforeAdvice111 implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            if (isCustomMethod(method.getName())) {
                System.out.println("[AOP1] 就是想记录谁消费了：" + args[0]);
            }
        }
    }

    /** 方法正常返回的增强222 */
    static class AfterReturningAdvice222 implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) {
            if (isCustomMethod(method.getName())) {
                System.out.println("[AOP2] 想看看买了啥：" + target.getClass().getSimpleName());
            }
        }
    }

    static boolean isCustomMethod(String methodName) {
        return !"toString".equals(methodName) && !"hashCode".equals(methodName) && !"equals".equals(methodName)
                && !"clone".equals(methodName);
    }

}
